package com.bestdata.em.drs.receviedatafromDRS.service;


import com.alibaba.fastjson.JSONObject;
import com.bestdata.em.drs.receviedatafromDRS.mapper.DataProcessMapper;
import com.bestdata.em.drs.receviedatafromDRS.model.DataInfo;
import com.bestdata.em.drs.receviedatafromDRS.model.InsertData;
import com.netty.im.client.core.EMDataConnection;
import com.netty.im.client.core.EMDataReceive;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author chizhenyu
 * @title:
 * @description: 接收DMS的数据
 * @date 2019-12-2 13:51:50
 */

@Service
@DependsOn("springContextHolder")
public class DataReceiveProcess extends Thread implements EMDataReceive {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private WebApplicationContext webapplicationcontext;

    @Autowired
    private DataProcessMapper dataProcessMapper;

    private Thread thread;
    @Value("${receive.clientKey}")
    private String clientKey = "";
    @Value("${receive.listenip}")
    private String dmsServiceIp = "";
    @Value("${receive.listenport}")
    private int dmsServicePort = 9111;
    @Value("${data.dataresources}")
    private String data = "";

    //测斜仪，区分X、Y轴
    private static final String INMV = "INMV_DeviceDataHist";
    //渗部水位
    private static final String WATL = "WATL_DeviceDataHist";
    //应力
    private static final String YB = "YB_DeviceDataHist";
    //缓存 EM设备ID，对应华测数据库信息
    private static Map<String, String> dMap = new HashMap<String, String>();
    //缓存 一级 为测斜仪提供缓存空间，拼装X、Y轴测点数据
    private static Map<String, Map<String,String>> INMVConfigMap = new HashMap<String, Map<String,String>>();


    @PostConstruct
    public void init() {
        DeviceInformationAnalysis();
        this.thread = new Thread(this);
        this.thread.start();
    }

    @Override
    public void run() {
        EMDataConnection emDataUtil = new  EMDataConnection();

        emDataUtil.start(clientKey,dmsServiceIp , dmsServicePort, this);
        logger.info("Client Key:" + clientKey + "," + dmsServiceIp + "," + dmsServicePort);
    }

    @Override
    public void ConsumptionData(String msg) {
        try {
            if (msg == null){
                logger.error("msg is null");
                return;
            }
            //解析接收json数组
            DataInfo deviceData = JSONObject.parseObject(msg, DataInfo.class);
            //EM设备ID
            String devid = deviceData.getDevid();
            //校验设备ID非空
            if(!StringUtils.isEmpty(devid)){
                //通过EM设备ID
                String valStr = dMap.get(devid);
                //判断map中是否包含EM设备ID信息
                if(!StringUtils.isEmpty(valStr)){
                    //解析出设备的配置信息(包含：华测数据库是吧ID，数据库名称，设备类型)
                    String[] devConfigs = valStr.split(",");

                    if(INMV.equals(devConfigs[1])){
                        //测斜仪
                        this.INMVDeviceDataProcess(devConfigs,deviceData);
                    } else if(WATL.equals(devConfigs[1])){
                        //渗部水位
                        this.WATLDeviceDataProcess(devConfigs,deviceData);
                    } else{
                        //应力
                        this.YBDeviceDataProcess(devConfigs,deviceData);
                    }
                }else{
                    logger.error("EM devID doesn't exist in dMap, devID : {}",devid);
                }
            }else{
                logger.error("EM devID is null");
            }


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 测斜仪
     * @param devConfigArr
     * @param deviceData
     */
    public void INMVDeviceDataProcess(String[] devConfigArr,DataInfo deviceData){

        //由华测数据库设备ID，查询该缓存中是否存有X、Y轴数据信息
        Map<String,String> devTypeMap = INMVConfigMap.get(devConfigArr[0]);

        if(StringUtils.isEmpty(devTypeMap)){
            Map<String,String> map = new HashMap<>();
            map.put(devConfigArr[2],deviceData.getValue());
            INMVConfigMap.put(devConfigArr[0],map);
            return;
        }

        InsertData data = new InsertData();
        //判断缓存中存在的设备XY轴，是否和刚接入的XY轴类型相同
        //若相同，则有value，表示缓存和刚接入的都是X/Y轴，错误数据：有一支传感器离线
        //若不同，则无value，表示缓存和刚接入的分别为X、Y轴，正确数据
        //X轴存V1，Y轴存V2
        if(StringUtils.isEmpty(devTypeMap.get(devConfigArr[2]))){
            //若刚接入数据为X轴
            if("X".equals(devConfigArr[2])){
                data.setX(deviceData.getValue());
                data.setY(devTypeMap.get("Y"));
            }else{
                data.setY(deviceData.getValue());
                data.setX(devTypeMap.get("X"));
            }
            data.setTm(new Date());
            data.setId(devConfigArr[0]);
            //执行插入
            boolean xyData = this.dataProcessMapper.insertXYData(data);

            if(xyData){
                logger.info(deviceData.getDevname()+" - is Insert successfully! data: {}",data);
            }else{
                logger.error(deviceData.getDevname()+" - is Insert failure! data: {}",data);
            }

            // 执行完存储过程后 删除缓存中的该华测数据库设备ID及对应信息
            Iterator<String> iterator = INMVConfigMap.keySet().iterator();
            // 循环取键值进行判断
            while (iterator.hasNext()){
                String key = iterator.next();
                if(key.equals(devConfigArr[0])){
                    // 移除map中键对应的键值对
                    iterator.remove();
                }
            }
        }else{
            //若缓存中的设备XY轴类型相同，则更新缓存中的数据
            devTypeMap.put(devConfigArr[2],deviceData.getValue());
            INMVConfigMap.put(devConfigArr[0],devTypeMap);
        }
    }

    /**
     * 渗压计
     * @param devConfigArr
     * @param deviceData
     */
    public void WATLDeviceDataProcess(String[] devConfigArr,DataInfo deviceData){
        InsertData data = new InsertData();
        //华测数据库对应设备ID
        data.setId(devConfigArr[0]);
        data.setX(deviceData.getValue());
        data.setTm(new Date());
        //insert 华测数据库，
        boolean insertData = this.dataProcessMapper.insertWATLData(data);

        if(insertData){
            logger.info(deviceData.getDevname()+" - is Insert successfully! data: {}",data);
        }else{
            logger.error(deviceData.getDevname()+" - is Insert failure! data: {}",data);
        }

    }

    /**
     * 应力
     * @param devConfigArr
     * @param deviceData
     */
    public void YBDeviceDataProcess(String[] devConfigArr,DataInfo deviceData){
        InsertData data = new InsertData();
        //华测数据库对应设备ID
        data.setId(devConfigArr[0]);
        data.setX(deviceData.getValue());
        data.setTm(new Date());
        //insert 华测数据库，
        boolean insertData = this.dataProcessMapper.insertYBData(data);

        if(insertData){
            logger.info(deviceData.getDevname()+" - is Insert successfully! data: {}",data);
        }else{
            logger.error(deviceData.getDevname()+" - is Insert failure! data: {}",data);
        }
    }


    /**
     * 设备ID和数据ID对应关系
     */
    public void DeviceInformationAnalysis(){

        //从配置文件 中取出写在其中的设备和数据库的对应关系
        String[] devInfos = data.split(";");
        for (int i = 0; i < devInfos.length; i++) {

            String[] devs = devInfos[i].split(":");
            //key: em中设备ID   value：[华测数据库中设备ID，数据库表，XY轴(空即为非测斜仪设备)]
            dMap.put(devs[0],devs[1]);

        }
        logger.info("dMap : "+dMap);
    }

}

